<template>
  <el-scrollbar ref="scrollbar">
    <slot></slot>
    <ul class="dotList">
      <li
        class="dot"
        :class="{active: currentIndex === index}"
        v-for="(item, index) in items"
        :key="index"
        @click="dotClick(index)"
      ></li>
    </ul>
  </el-scrollbar>
</template>

<script>
import Velocity from 'velocity-animate'
// import { debounce } from '@/common/js/util'
const ISMOBILD = /Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)

export default {
  name: 'DropCarousel',
  data() {
    return {
      isAnimate: false,
      items: [],
      currentIndex: 0
    }
  },
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    value: {
      type: Number,
      default: 0
    }
  },
  created() {
    this.touch = {}
  },
  mounted() {
    this._updateItems()
    this._handleResize()
    this._addEvent()
  },
  methods: {
    // 事件绑定
    _addEvent() {
      const scrollbar = this.$refs.scrollbar.$el
      const listWrapper = scrollbar.querySelector('.el-scrollbar__wrap')
      scrollbar.addEventListener('mousewheel', this._handleMousewheel)
      listWrapper.addEventListener('scroll', this._handleScroll)
      window.addEventListener('resize', this._handleResize)

      // 若为移动端则禁止原生滚动
      if (ISMOBILD) {
        listWrapper.style.overflowY = 'hidden'
        listWrapper.addEventListener('touchstart', this.scrollTouchStart)
        listWrapper.addEventListener('touchmove', this.scrollTouchMove)
        listWrapper.addEventListener('touchend', this.scrollTouchEnd)
      }
    },

    // 时间移除
    _removeEvent() {
      const scrollbar = this.$refs.scrollbar.$el
      const listWrapper = scrollbar.querySelector('.el-scrollbar__wrap')
      scrollbar.removeEventListener('mousewheel', this._handleMousewheel)
      listWrapper.removeEventListener('scroll', this._handleScroll)
      window.removeEventListener('resize', this._handleResize)

      if (ISMOBILD) {
        listWrapper.removeEventListener('touchstart', this.scrollTouchStart)
        listWrapper.removeEventListener('touchmove', this.scrollTouchMove)
        listWrapper.removeEventListener('touchend', this.scrollTouchEnd)
      }
    },

    scrollTouchStart(e) {
      this.touch.initiated = true
      const touch = e.touches[0]
      this.touch.startX = touch.pageX
      this.touch.startY = touch.pageY
      this.deltaX = undefined
      this.deltaY = undefined
    },

    scrollTouchMove(e) {
      const touch = e.touches[0]
      this.deltaX = touch.pageX - this.touch.startX
      this.deltaY = touch.pageY - this.touch.startY
    },

    scrollTouchEnd(e) {
      // 手势主要是操作Y轴
      if (Math.abs(this.deltaX) < Math.abs(this.deltaY) && Math.abs(this.deltaY) > 20) {
        this.deltaY > 0 ? this._setCurrentIndex('-') : this._setCurrentIndex('+')
      }

      this.$emit('touchEnd', {
        deltaX: this.deltaX,
        deltaY: this.deltaY
      })
    },

    dotClick(index) {
      if (this.isAnimate) {
        return
      }
      this._setCurrentIndex(index)
    },

    scrollbarDOM(index) {
      if (index === undefined || this.isAnimate) {
        return
      }
      const scrollbar = this.$refs.scrollbar.$el
      const listWrapper = scrollbar.querySelector('.el-scrollbar__wrap')
      const listTarget = this.items[index].$el

      Velocity(listTarget, 'scroll', {
        begin: () => {
          this.isAnimate = true
        },
        complete: () => {
          this.isAnimate = false
        },
        container: listWrapper
      })
    },

    _handleScroll(e) {
      if (this.isAnimate || this.touch.initiated) {
        return
      }
      // 滚动中节流
      if (this.scrollTimer) {
        clearTimeout(this.scrollTimer)
      }
      this.scrollTimer = setTimeout(() => {
        // console.log('scrollTimer')
        let index = e.target.scrollTop / this.visualHeight | 0
        const scale = (e.target.scrollTop % this.visualHeight) / this.visualHeight
        // 屏幕中下一张图片占的比例多
        if (scale > 0.5) {
          index++
          this._setCurrentIndex(index)
        }
      }, 20)

      // 滚动结束
      if (this.scrollEndTimer) {
        clearTimeout(this.scrollEndTimer)
      }
      this.scrollEndTimer = setTimeout(() => {
        // console.log('scrollEndTimer')
        this.scrollbarDOM(this.currentIndex)
      }, 1500)
    },

    _handleMousewheel(e) {
      // 阻止默认滚动
      e.preventDefault()

      // 再次滚轮遇到 动画执行中 时终止滚轮触发事件
      if (this.isAnimate) {
        return
      }

      if (e.deltaY > 0 && !(this.currentIndex === this.items.length - 1)) {
        this._setCurrentIndex('+')
        return true
      }

      if (e.deltaY < 0 && !(this.currentIndex === 0)) {
        this._setCurrentIndex('-')
        return true
      }
    },

    _handleResize() {
      if (this.resizeTimer) {
        clearTimeout(this.resizeTimer)
      }
      this.resizeTimer = setTimeout(() => {
        const scrollbar = this.$refs.scrollbar.$el
        const scrollH = scrollbar.clientHeight

        this.visualHeight = scrollH

        this.items.forEach((item) => {
          // 子元素高度不铺满
          if (!item.$props.inline) {
            item.$el.style.height = scrollH + 'px'
          }
          // console.log(item.$props.inline)
        })
        this.$emit('handleResize', scrollH)
      }, 50)
    },

    _updateItems() {
      let ret = []

      this.$slots.default.forEach((VNode) => {
        const VueComponent = VNode.child
        if (VueComponent && VueComponent.$options.name === 'DropCarouselItem') {
          // ret.push(VueComponent.$el)
          ret.push(VueComponent)
        }
      })

      this.items = ret

      return ret
    },

    _setCurrentIndex(index) {
      const itemLeng = this.items.length

      // 如果是数字类型
      if (typeof index === 'number') {
        if ((index < 0 || index > itemLeng - 1)) {
          return
        } else {
          this.currentIndex = index
          return
        }
      }

      // 如果是字符类型
      if (index === '+' && !(this.currentIndex >= itemLeng - 1)) {
        this.currentIndex++
        return
      }

      if (index === '-' && !(this.currentIndex <= 0)) {
        this.currentIndex--
        return true
      }
    }
  },
  activated() {
    this._handleResize()
    this._addEvent()
  },
  deactivated() {
    this._removeEvent()
  },
  beforeDestroy() {
    this._removeEvent()
  },
  watch: {
    currentIndex(newI) {
      this.$emit('change', newI)
      this.scrollbarDOM(newI)
    }
  }
}
</script>

<style lang="stylus" scoped>
.dotList
  position: absolute
  top: 50%
  right: 50px
  transform: translateY(-50%)
  li.dot
    cursor: pointer
    width: 15px
    height: @width
    border-radius: @width
    margin: 10px 0
    border: 2px solid rgba(255, 255, 255, 0.5)
    transition: background-color .3s
    &.active
      background-color: rgba(255, 255, 255, 0.8)

</style>
